﻿// <copyright file="ElementBase.cs" company="Marcin Wosik">
// Copyright (c) 2010 All Right Reserved
// </copyright>
// <author>Marcin Wosik</author>
// <email>mawo11@gmail.com</email>
// <date>2010-02-25</date>
// <summary></summary>
namespace GameOfLife.GameData
{
    using System.Collections.Generic;
    using System.Windows;
    using System.Windows.Media;
    using System.Windows.Shapes;
    using GameOfLife.Interfaces;

    /// <summary>
    /// Base class of element 
    /// </summary>
    public abstract class ElementBase : IElement
    {
        #region Fields

        internal static SolidColorBrush BlackBrush = new SolidColorBrush(Colors.Black);
        internal static SolidColorBrush BlueBrush = new SolidColorBrush(Colors.Blue);
        internal static SolidColorBrush GreenBrush = new SolidColorBrush(Colors.Green);
        internal static SolidColorBrush RedBrush = new SolidColorBrush(Colors.Red);
        internal static SolidColorBrush WhiteBrush = new SolidColorBrush(Colors.White);
        internal static SolidColorBrush YellowBrush = new SolidColorBrush(Colors.Yellow);

        #endregion Fields

        #region Constructors

        protected ElementBase()
        {
            ConnectedElements = new List<IElement>();
        }

        #endregion Constructors

        #region Properties

        public ColorMode ColoringMode
        {
            get;
            set;
        }

        public IList<IElement> ConnectedElements
        {
            get;
            private set;
        }

        public ElementState Current
        {
            get;
            set;
        }

        public Polygon Drawer
        {
            get;
            set;
        }

        public bool IsAlive
        {
            get { return this.Current == ElementState.Created || this.Current == ElementState.Existing; }
        }

        public ElementState NewState
        {
            get;
            set;
        }

        public int PosX
        {
            get;
            set;
        }

        public int PosY
        {
            get;
            set;
        }

        #endregion Properties

        #region Methods

        public static IElement GetFromCord(IList<IElement> data, int posX, int posY)
        {
            for (int i = 0; i < data.Count; ++i)
            {
                if (data[i].PosX == posX && data[i].PosY == posY)
                {
                    return data[i];
                }
            }

            return null;
        }

        public virtual void ChangeState()
        {
            if (this.Current == this.NewState)
            {
                return;
            }

            this.Current = this.NewState;

            UpdateColor();
        }

        public virtual bool CheckCord(Point pt)
        {
            return false;
        }

        public virtual void MakeConnection(GameSettings data)
        {
            if (this.ConnectedElements != null)
            {
                this.ConnectedElements.Clear();
            }
        }

        public virtual void UpdateColor()
        {
            switch (this.Current)
            {
                case ElementState.Created:
                    switch (this.ColoringMode)
                    {
                        case ColorMode.Default:
                            this.Drawer.Fill = BlackBrush;
                            break;
                        case ColorMode.Simple:
                            this.Drawer.Fill = GreenBrush;
                            break;
                        case ColorMode.Immigration:
                            this.Drawer.Fill = this.CalculateImmigration();
                            break;
                        case ColorMode.QuadLife:
                            this.Drawer.Fill = this.CalculateQuadLife();
                            break;
                    }

                    break;
                case ElementState.Dead:
                    if (this.ColoringMode == ColorMode.Simple)
                    {
                        this.Drawer.Fill = RedBrush;
                    }
                    else
                    {
                        this.Drawer.Fill = WhiteBrush;
                    }
                    break;
                case ElementState.Existing:
                    switch (this.ColoringMode)
                    {
                        case ColorMode.Default:
                            this.Drawer.Fill = BlackBrush;
                            break;
                        case ColorMode.Simple:
                            this.Drawer.Fill = YellowBrush;
                            break;
                    }
                    break;
                case ElementState.None:
                    this.Drawer.Fill = WhiteBrush;
                    break;
            }
        }

        private Brush CalculateImmigration()
        {
            Dictionary<Brush, int> colors = new Dictionary<Brush, int>(2);
            colors.Add(RedBrush, 0);
            colors.Add(YellowBrush, 0);

            for (int i = 0; i < ConnectedElements.Count && i < 2; ++i)
            {
                Brush key = ConnectedElements[i].Drawer.Fill;
                if (key != null && colors.ContainsKey(key))
                {
                    colors[key]++;
                }
            }
            return colors[RedBrush] >= colors[YellowBrush] ? RedBrush : YellowBrush;
        }

        private Brush CalculateQuadLife()
        {
            Dictionary<Brush, int> colors = new Dictionary<Brush, int>(4);
            colors.Add(RedBrush, 0);
            colors.Add(BlueBrush, 0);
            colors.Add(YellowBrush, 0);
            colors.Add(GreenBrush, 0);

            for (int i = 0; i < ConnectedElements.Count && i < 2; ++i)
            {
                Brush key = ConnectedElements[i].Drawer.Fill;
                if (key != null && colors.ContainsKey(key))
                {
                    colors[ConnectedElements[i].Drawer.Fill]++;
                }
            }

            Brush maxColor = null;
            Brush minColor = null;
            foreach (KeyValuePair<Brush, int> pair in colors)
            {
                if (pair.Value == 0)
                {
                    minColor = pair.Key;
                }
                if (pair.Value > 1)
                {
                    maxColor = pair.Key;
                }

            }

            return minColor == null ? maxColor : minColor;
        }

        #endregion Methods
    }
}